/*
 *  Copyright 2004 Blandware (http://www.blandware.com)
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package com.blandware.atleap.webapp.struts;

import com.blandware.atleap.webapp.util.core.TileContainerUtil;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.struts.tiles.NoSuchDefinitionException;
import org.apache.struts.tiles.xmlDefinition.DefinitionsFactory;
import org.apache.struts.tiles.xmlDefinition.XmlDefinition;
import org.apache.struts.tiles.xmlDefinition.XmlDefinitionsSet;

import javax.servlet.ServletContext;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * <p>A factory for definitions.
 * This factory allows to retrieve definitions by their keys.</p>
 * <p>It also modifies some definitions according to data in DB.</p>
 * <p><a href="HeritableDefinitionsFactory.java.html"><i>View Source</i></a></p>
 * <p/>
 *
 * @author Andrey Grebnev <a href="mailto:andrey.grebnev@blandware.com">&lt;andrey.grebnev@blandware.com&gt;</a>
 * @author Roman Puchkovskiy <a href="mailto:roman.puchkovskiy@blandware.com">
 *         &lt;roman.puchkovskiy@blandware.com&gt;</a>
 * @version $Revision: 1.7 $ $Date: 2007/04/07 13:05:01 $
 */
public class HeritableDefinitionsFactory extends DefinitionsFactory {

	/**
	 * Commons Logging instance.
	 */
	protected static Log log = LogFactory.getLog(HeritableDefinitionsFactory.class);

    /**
     * Servlet context
     */
    protected ServletContext servletContext = null;


    /**
	 * Constructor.
	 * Creates a factory initialized with definitions from {@link org.apache.struts.tiles.xmlDefinition.XmlDefinitionsSet}.
	 *
	 * @param xmlDefinitions Resolved definition from XmlDefinitionSet.
	 * @param servletContext Servlet context
     * @throws org.apache.struts.tiles.NoSuchDefinitionException
	 *          If an error occurs while resolving inheritance
	 */
	public HeritableDefinitionsFactory(XmlDefinitionsSet xmlDefinitions,
                                       ServletContext servletContext)
	        throws NoSuchDefinitionException {
		super(xmlDefinitions);

        // Save servlet context, init application context
        this.servletContext = servletContext;

        // Walk thru xml set and copy each definition.
        storeDefinitions(xmlDefinitions);

        TileContainerUtil tileContainerUtil
                = TileContainerUtil.getInstance(servletContext);
        tileContainerUtil.initialize(definitions, this);
    }

    /**
     * Stores definitions from XmlDefinitionSet to map.
     *
     * @param xmlDefinitions set of definitions
     */
    protected void storeDefinitions(XmlDefinitionsSet xmlDefinitions) {
        ContainedXmlDefinition definition;
        boolean isContained;

        definitions = new HashMap();

        Iterator i = xmlDefinitions.getDefinitions().values().iterator();
        while (i.hasNext()) {
            XmlDefinition xmlDefinition = (XmlDefinition) i.next();
            isContained = xmlDefinition instanceof ContainedXmlDefinition;
            if (isContained) {
                definition = (ContainedXmlDefinition) xmlDefinition;
                putDefinition(new HeritableComponentDefinition(definition));
            } else {
                putDefinition(new HeritableComponentDefinition(xmlDefinition));
            }
        }
    }

    /**
     * Gets a mapping from definition names to definitions that can be
     * manufactured by this factory
     *
     * @return mapping from definition names to definitions
     */
	public Map getDefinitions() {
		return definitions;
	}

    /**
     * Sets a mapping from definition names to definitions that can be
     * manufactured by this factory.
     *
     * @param definitions mapping from definition names to definitions
     */
    public void setDefinitions(Map definitions) {
        this.definitions = definitions;
    }

}
